/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.center.web.action.integration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import com.sinodata.bsm.center.bean.ResTypeBean;
import com.sinodata.bsm.center.cache.ProbeCache;
import com.sinodata.bsm.center.cache.ResAttrValCache;
import com.sinodata.bsm.center.cache.ResCache;
import com.sinodata.bsm.center.cache.ResRelationCache;
import com.sinodata.bsm.center.cache.ResTypeCache;
import com.sinodata.bsm.center.engine.resource.find.FindResBean;
import com.sinodata.bsm.center.engine.resource.find.FindResFactory;
import com.sinodata.bsm.center.engine.resource.find.FindResGroup;
import com.sinodata.bsm.center.message.Messenger;
import com.sinodata.bsm.center.service.probe.ProbeService;
import com.sinodata.bsm.center.service.relation.ResRelationService;
import com.sinodata.bsm.center.service.resource.AttributeService;
import com.sinodata.bsm.center.service.resource.ResService;
import com.sinodata.bsm.center.util.web.Struts2Utils;
import com.sinodata.bsm.center.web.action.BaseAction;
import com.sinodata.bsm.common.constants.RelationConstants;
import com.sinodata.bsm.common.constants.ResConstants;
import com.sinodata.bsm.common.message.ServiceMessage;
import com.sinodata.bsm.common.vo.Attribute;
import com.sinodata.bsm.common.vo.Probe;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResAttrVal;
import com.sinodata.bsm.common.vo.ResRelation;

/**
 * <p>
 * Description: 集成网络监控系统
 * </p>
 *
 * @author wangyazhou
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-11-14 下午2:20:24          wangyazhou        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class InmpAction extends BaseAction<Object> {

    private static Map<String, String> changeMap = new HashMap<String, String>();
    private static final long serialVersionUID = 1L;
    private Long id;
    private Res entity;
    @Autowired
    private ResCache resCache;
    @Autowired
    private ResTypeCache resTypeCache;
    @Autowired
    private ResAttrValCache resAttrValCache;
    @Autowired
    private ProbeCache probeCache;
    @Autowired
    private ResRelationCache resRelationCache;
    @Autowired
    private ProbeService probeService;
    @Autowired
    private ResService resService;
    @Autowired
    private AttributeService attributeService;
    @Autowired
    private ResRelationService resRelationService;

    @SuppressWarnings("unchecked")
    public String guide() {
        List<Probe> probeList = probeService.findAllInmpProbe();
        Collections.sort(probeList, new ProbeSort());
        request.setAttribute("probeList", probeList);
        request.setAttribute("id", id);
        request.setAttribute("viewId", request.getParameter("viewId"));
        return "guide";
    }

    @Override
    public String list() throws Exception {
        return null;
    }

    /**
     * 获取网络资源列表
     * @return 
     * @throws Exception 
     * @throws NumberFormatException 
     */
    @SuppressWarnings("unchecked")
    public String getNodeList() {
        Long viewId = Long.valueOf(request.getParameter("viewId"));
        String probeId = request.getParameter("probeId");
        String flag = request.getParameter("flag");
        ServiceMessage message = new ServiceMessage();
        message.setSrvId("ResFindService");
        message.setMethod("getNetDeviceList");
        List<String[]> list = null;
        Object result = null;
        try {
            if (!probeId.equals("") && !probeId.equals("-1")) {
                result = Messenger.getInstance().sendSyncMessage(Long.parseLong(probeId), message);
            }
            if (result == null) {
                JSONObject json = new JSONObject();
                json.element("iTotalRecords", 0);
                json.element("iTotalDisplayRecords", 0);
                JSONArray array = new JSONArray();
                json.element("aaData", array);
                renderText(json.toString());
                return null;
            }

            //tdd
            //            System.out.println(result);s
            list = (List<String[]>) result;

            if (probeId.equals("")) {
                JSONObject json = new JSONObject();
                json.element("iTotalRecords", 0);
                json.element("iTotalDisplayRecords", 0);
                JSONArray array = new JSONArray();
                json.element("aaData", array);
                renderText(json.toString());
            } else {
                JSONObject json = new JSONObject();
                json.element("iTotalRecords", list.size());
                json.element("iTotalDisplayRecords", list.size());
                JSONArray array = new JSONArray();
                for (String[] sy : list) {
                    JSONObject obj = new JSONObject();
                    //如果缓存中存在这个资源  并且已存在的资源不在此视图下
                    Res res = resCache.getResByIpType(sy[3], Long.parseLong(sy[4]));
                    if (res != null) {
                        obj.element("probeName", "<div style='color:gray;text-decoration:line-through;'>" + probeCache.get(Long.parseLong(probeId)).getName() + "</div>");
                        obj.element("resName", "<div style='color:gray;text-decoration:line-through;'>" + sy[1] + "</div>");
                        obj.element("ip", "<div style='color:gray;text-decoration:line-through;'>" + sy[3] + "</div>");
                        obj.element("resTypeName", "<div style='color:gray;text-decoration:line-through;'>" + resTypeCache.get(Long.parseLong(sy[4])).getName() + "</div>");
                        if (flag.equals("0")) {
                            if (sy[0].equals(res.getInternalId())) {
                                obj.element("change", "已存在,只需重新发现");
                            } else {
                                obj.element("change", "已存在,但需重新添加");
                            }
                        } else {
                            obj.element("change", "<div style='color:gray;text-decoration:line-through;'>" + changeMap.get(sy[0]) == null ? "" : changeMap.get(sy[0]) + "</div>");
                        }
                    } else {
                        obj.element("probeName", probeCache.get(Long.parseLong(probeId)).getName());
                        obj.element("resName", sy[1]);
                        obj.element("ip", sy[3]);
                        obj.element("resTypeName", resTypeCache.get(Long.parseLong(sy[4])).getName());
                        if (flag.equals("0")) {
                            obj.element("change", "新增");
                        } else {
                            obj.element("change", changeMap.get(sy[0]) == null ? "" : changeMap.get(sy[0]));
                        }
                    }
                    array.add(obj);
                }
                json.element("aaData", array);
                renderText(json.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e);
        }
        return null;
    }

    /**
     * 执行网络设备的发现的添加操作
     * @throws Exception
     */
    public void add() throws Exception {
        changeMap.clear();
        JSONObject json = new JSONObject();
        try {
            String viewId = request.getParameter("viewId");
            String probeId = request.getParameter("probeId");
            String parentId = request.getParameter("parentId");

            //获取网络设备列表
            ServiceMessage message = new ServiceMessage();
            message.setSrvId("ResFindService");
            message.setMethod("getNetNodeList");
            List<String[]> list = (List<String[]>) Messenger.getInstance().sendSyncMessage(Long.parseLong(probeId), message);

            //获取资源类别列表
            ServiceMessage message1 = new ServiceMessage();
            message1.setSrvId("ResFindService");
            message1.setMethod("getNetTypeSet");
            Set<Long> typeSet = (Set<Long>) Messenger.getInstance().sendSyncMessage(Long.parseLong(probeId), message1);

            //主资源列表
            List<Res> allResList = new ArrayList<Res>();
            //添加主资源  修改:
            this.addTopRes(viewId, list, allResList, Long.valueOf(probeId), Long.parseLong(parentId), typeSet);

            //资源的变化情况
            int index = 0;
            for (Res res : allResList) {
                //添加子资源及属性
                String iinId = list.get(index++)[0];
                this.addRes(res, Long.valueOf(probeId), iinId);
            }
            //添加资源之间的关系
            this.addRelation(probeId);
            json.element("flag", "success");
        } catch (Exception e) {
            e.printStackTrace();
            json.element("flag", "error");
        } finally {
            Struts2Utils.renderText(json.toString());
        }
    }

    //添加资源之间的关系
    private void addRelation(String probeId) throws Exception {
        ServiceMessage message = new ServiceMessage();
        message.setSrvId("ResFindService");
        message.setMethod("getRelationList");
        List<String[]> list = (List<String[]>) Messenger.getInstance().sendSyncMessage(Long.parseLong(probeId), message);
        List<ResRelation> resRelationList = new ArrayList<ResRelation>();
        for (String[] array : list) {
            Long startId = Long.valueOf(array[0]);
            Long endId = Long.valueOf(array[2]);
            Long relationTypeId = Long.valueOf(array[1]);
            if (!isExitRelation(startId, endId, relationTypeId)) {
                ResRelation resRelation = new ResRelation();
                resRelation.setStartId(startId);
                resRelation.setEndId(endId);
                resRelation.setRelationTypeId(relationTypeId);
                resRelationList.add(resRelation);
            }
        }
        resRelationService.batchAddResRelation(resRelationList);
        for (ResRelation resRelation : resRelationList) {
            resRelationCache.addResRelation(resRelation);
        }
    }

    /**
     * 添加主资源  只添加列表中新增的
     * @param viewId
     * @param list
     * @param allResList
     * @param probeId
     * @throws Exception
     * list 格式如下：1281,1281 中间业务路由  ''  10.3.7.54 3101020000000
     *                internalid 名称               描述    ip        类别id
     */
    private void addTopRes(String viewId, List<String[]> list, List<Res> allResList, Long probeId, Long parentId, Set<Long> netSet) throws Exception {
        List<Res> addResList = new ArrayList<Res>();
        List<Res> deleteResList = new ArrayList<Res>();

        List<Res> noChange = new ArrayList<Res>();
        List<Res> oldList = resCache.getResInSet(netSet);
        for (String[] stry : list) {
            if (stry[0] == null || stry[0].length() == 0 || stry[3] == null || stry[3].length() == 0 || stry[4] == null || stry[4].length() == 0) {
                continue;
            }
            Res res = resCache.getResByIpType(stry[3], Long.parseLong(stry[4]));
            if (res != null && res.getInternalId().equals(stry[0])) {
                noChange.add(res);
                allResList.add(res);
            } else {
                res = new Res();
                res.setProbeId(probeId);
                res.setInternalId(stry[0]);
                res.setName(stry[1]);
                res.setDesc(stry[2]);
                res.setIp(stry[3]);
                res.setResTypeId(Long.valueOf(stry[4]));
                res.setHealthStatus(ResConstants.NORMAL_USABLE);
                res.setPaused(ResConstants.RES_NOT_PAUSED);
                res.setDeleted(0);
                res.setHealthDegree(100);
                addResList.add(res);
                allResList.add(res);
            }
        }

        //计算要删除的资源
        for (Res res : oldList) {
            boolean b = false;
            for (Res nres : noChange) {
                if (res.getId() == nres.getId()) {
                    b = true;
                    continue;
                }
            }
            if (!b) {
                deleteResList.add(res);
            }
        }

        //批量删除资源
        for (Res dRes : deleteResList) {
            //            resService.deleteResource(parentId, dRes.getId())
            resService.deleteResAll(dRes.getId());
        }

        //批量新加资源
        for (Res res : addResList) {
            List<ResAttrVal> attValList = new ArrayList<ResAttrVal>();
            ResTypeBean bean = ResTypeBean.get(res.getResTypeId());
            List<Attribute> attList = bean.attributes();
            //            for (int a = 0; attList != null && a < attList.size(); a++) {
            //                Attribute attribute = attList.get(a);
            //                //封装ResAttrVal
            //                ResAttrVal attval = new ResAttrVal();
            //                attval.setAttrId(attribute.getId());
            //                String attrValue = "";
            //                attval.setAttrValue(attrValue);
            //                attValList.add(attval);
            //            }
            resService.addResource(parentId, res, attValList, RelationConstants.SUPPORT);
        }
    }

    //添加子资源及属性
    private void addRes(Res res, Long probeId, String iinId) throws Exception {
        ServiceMessage message = new ServiceMessage();
        message.setSrvId("ResFindService");
        message.setMethod("getNodeInfoList");
        message.setParams(new Object[] { res.getInternalId() });
        //子资源及属性集合
        @SuppressWarnings("unchecked")
        List<String[]> list = (List<String[]>) Messenger.getInstance().sendSyncMessage(probeId, message);

        FindResGroup group = FindResFactory.getInstance().getResGroup(res.getId());
        group.setFinish(false);
        group.build();
        int index = 0;
        boolean flag = false;
        for (String[] result : list) {
            if (index++ > 0) {
                //子资源 每条进行比较 检查变化的
                group.getParents().checkChange(result);
            } else {
                //添加主资源属性
                int index1 = 4;
                List<Attribute> attributes = getAttributes(Long.valueOf(result[3]));
                if (attributes.size() == result.length - 4) {
                    for (Attribute attr : attributes) {
                        Long attrId = attr.getId();
                        ResAttrVal val = resAttrValCache.get(res.getId(), attrId);
                        if (val == null || val.getAttrValue() == null || (val.getAttrValue() != null && !val.getAttrValue().equals(result[index1]))) {
                            ResAttrVal resAttrVal = new ResAttrVal();
                            resAttrVal.setResId(res.getId());
                            resAttrVal.setAttrId(attrId);
                            resAttrVal.setAttrValue(result[index1]);
                            resAttrVal.setTime(new Date());
                            attributeService.saveResAttrVal(resAttrVal);
                            flag = true;
                        }
                        index1++;
                    }
                }
            }
        }
        //记录变化
        Map<Long, Long> addChangMap = new HashMap<Long, Long>();
        Map<Long, Long> updateChangMap = new HashMap<Long, Long>();
        //添加或者修改子资源
        List<FindResBean> beanList = group.getAllBeans();
        for (FindResBean bean : beanList) {
            if (bean.isChanged()) {
                int changeType = bean.getChangeType();
                if (changeType == FindResBean.CHANGE_ADD) {
                    getChangeMap(bean, addChangMap);
                    //增加
                    changeAdd(bean);
                } else if (changeType == FindResBean.CHANGE_MOD) {
                    getChangeMap(bean, updateChangMap);
                    //修改
                    changeMod(bean);
                } else if (changeType == FindResBean.CHANGE_DEL) {
                    changeDel(bean);
                }
            }
        }
        group.build();
        group.setFinish(true);
        changeMap.put(iinId, flag == true ? "主资源属性变化了," + getChange(addChangMap, updateChangMap) : getChange(addChangMap, updateChangMap));
        //返回发生的变化
    }

    private void getChangeMap(FindResBean bean, Map<Long, Long> changMap) {
        if (changMap.containsKey(bean.getRes().getResTypeId())) {
            Long value = changMap.get(bean.getRes().getResTypeId()) == null ? 0 : changMap.get(bean.getRes().getResTypeId()) + 1;
            changMap.put(bean.getRes().getResTypeId(), value);
        } else {
            changMap.put(bean.getRes().getResTypeId(), 1l);
        }
    }

    private String getChange(Map<Long, Long> addChangMap, Map<Long, Long> updateChangMap) {
        StringBuffer change = new StringBuffer();
        if (addChangMap.keySet() != null && addChangMap.keySet().size() != 0) {
            change.append("增加了");
            for (Long resTypeId : addChangMap.keySet()) {
                Long num = addChangMap.get(resTypeId);
                change.append(num).append("个").append(resTypeCache.get(resTypeId).getName()).append(",");
            }
        }
        if (updateChangMap.keySet() != null && updateChangMap.keySet().size() != 0) {
            change.append("修改了");
            for (Long resTypeId : updateChangMap.keySet()) {
                Long num = updateChangMap.get(resTypeId);
                change.append(num).append("个").append(resTypeCache.get(resTypeId).getName()).append(",");
            }
        }
        if (change == null || change.length() == 0) {
            change.append("子资源无变化");
        } else {
            change.delete(change.lastIndexOf(","), change.length());
        }
        return change.toString();
    }

    private void changeAdd(FindResBean bean) {
        Res res = bean.getRes();
        res.setHealthStatus(ResConstants.NORMAL_USABLE);
        res.setPaused(ResConstants.RES_NOT_PAUSED);
        List<ResAttrVal> attValList = bean.getChangeAttrValues();
        Long parentResId = bean.getParent().getRes().getId();
        resService.addResource(parentResId, res, attValList, RelationConstants.FORM);
    }

    private void changeMod(FindResBean bean) {
        Res res = bean.getRes();
        List<ResAttrVal> attValList = bean.getChangeAttrValues();
        for (ResAttrVal attrVal : attValList) {
            ResAttrVal oldVal = attributeService.getResAttrVal(res.getId(), attrVal.getAttrId());
            ResAttrVal savedVal = null;
            if (oldVal != null) {
                //修改
                oldVal.setAttrValue(attrVal.getAttrValue());
                savedVal = oldVal;
            } else {
                //新增
                attrVal.setResId(res.getId());
                savedVal = attrVal;
            }
            attributeService.saveResAttrVal(savedVal);

        }
    }

    private void changeDel(FindResBean bean) {
        Res res = bean.getRes();
        resService.deleteResource(this.id, res.getId().longValue());
    }

    private List<Attribute> getAttributes(Long resTypeId) {
        List<Attribute> resTypeAttributes = ResTypeBean.get(resTypeId).attributes();
        return resTypeAttributes;
    }

    private boolean isExitRelation(Long startResId, Long endResId, Long relationTypeId) {
        boolean flag = false;
        Long[] resIdArray1 = resRelationCache.getResByRelation(startResId, relationTypeId);
        Arrays.sort(resIdArray1);
        if (Arrays.binarySearch(resIdArray1, endResId) > -1) {
            flag = true;
        }
        if (!flag) {
            Long[] resIdArray2 = resRelationCache.getResByRelation(endResId, relationTypeId);
            Arrays.sort(resIdArray2);
            if (Arrays.binarySearch(resIdArray2, startResId) > -1) {
                flag = true;
            }
        }
        return flag;
    }

    @Override
    public Object getModel() {
        return entity;
    }

    @Override
    public String save() throws Exception {
        return null;
    }

    @Override
    public String delete() throws Exception {
        return null;
    }

    @Override
    protected void prepareModel() throws Exception {

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @SuppressWarnings("rawtypes")
    class ProbeSort implements Comparator {
        @Override
        public int compare(Object obj1, Object obj2) {
            Probe res1 = (Probe) obj1;
            Probe res2 = (Probe) obj2;
            if (Math.abs(res1.getStatus() - 3) > Math.abs(res2.getStatus() - 3)) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    @Override
    public String input() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }
}
